package com.sq.util;

import java.io.File;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sq.util.encrypt.SignUtil;

/**
 * @author sq
 *
 */
public class FileUtil {

    private static Logger log = LoggerFactory.getLogger(FileUtil.class);

    public static void makeParentDir(File file) {
        File dir = new File(file.getParent());
        if (!dir.exists()) {
            dir.mkdirs();
        }
    }

    public static String getFileMd5(File file) {
        return SignUtil.md5(file);
    }

    /**
     * 递归获取本级以下的文件
     */
    public static List<File> listAllFiles(File file) {
        LinkedList<File> result = new LinkedList<>();
        Set<String> fileNames = new HashSet<>();
        listAllFiles(file, null, result, fileNames);
        return result;
    }

    public static List<File> listAllFiles(File file, String[] extensions) {
        LinkedList<File> result = new LinkedList<>();
        Set<String> fileNames = new HashSet<>();
        String[] newExtensions = null;
        if (extensions != null) {
            // 转成小写
            int len = extensions.length;
            newExtensions = new String[len];
            for (int i = 0; i < len; i++) {
                newExtensions[i] = extensions[i].toLowerCase();
            }
        }
        listAllFiles(file, newExtensions, result, fileNames);
        return result;
    }

    public static List<File> listAllDirs(File dir) {
        LinkedList<File> result = new LinkedList<>();
        Set<String> dirNames = new HashSet<>();
        listAllDirs(dir, result, dirNames);
        return result;
    }

    public static List<File> listAllEmptyDirs(File dir) {
        LinkedList<File> result = new LinkedList<>();
        Set<String> dirNames = new HashSet<>();
        listAllEmptyDirs(dir, result, dirNames);
        return result;
    }

    /**
     * 下一级全是文件夹
     */
    public static boolean allSonIsDir(File dir) {
        for (File sonFile : dir.listFiles()) {
            if (!sonFile.isDirectory()) {
                return false;
            }
        }
        return true;
    }

    /**
     * 下一级全是文件
     */
    public static boolean allSonIsFile(File dir) {
        for (File sonFile : dir.listFiles()) {
            if (!sonFile.isFile()) {
                return false;
            }
        }
        return true;
    }

    public static void deleteAllSon(File dir) {
        String baseDirAbsolutePath = dir.getAbsolutePath();
        for (File sonFile : dir.listFiles()) {
            if (sonFile.isDirectory()) {
                deleteAllSon(sonFile);
                if (sonFile.listFiles().length == 0) {
                    log.info("删除文件夹:" + sonFile.getAbsolutePath());
                    sonFile.delete();
                }
            } else {
                String path = sonFile.getAbsolutePath();
                if (StringUtil.startWith(path, baseDirAbsolutePath)) {
                    log.info("删除文件:" + path);
                    sonFile.delete();
                }
            }
        }
        // 如果文件夹为空了，删除该文件夹
        if (dir.listFiles().length == 0) {
            log.info("删除文件夹:" + baseDirAbsolutePath);
            dir.delete();
        }
    }

    private static void listAllEmptyDirs(File dir, LinkedList<File> result, Set<String> dirNames) {
        if (!dir.isDirectory()) {
            return;
        }
        if (dirNames.contains(dir.getAbsolutePath())) {
            return;
        }
        dirNames.add(dir.getAbsolutePath());
        File[] tempList = dir.listFiles();
        if (tempList.length < 1) {
            result.add(dir);
            return;
        }
        for (File f : tempList) {
            listAllEmptyDirs(f, result, dirNames);
        }
    }

    private static void listAllDirs(File dir, LinkedList<File> result, Set<String> dirNames) {
        if (!dir.isDirectory()) {
            return;
        }
        if (dirNames.contains(dir.getAbsolutePath())) {
            return;
        }
        result.add(dir);
        dirNames.add(dir.getAbsolutePath());
        File[] tempList = dir.listFiles();
        if (tempList.length < 1) {
            return;
        }
        for (File f : tempList) {
            listAllDirs(f, result, dirNames);
        }
    }

    private static void listAllFiles(File file, String[] extensions, LinkedList<File> result, Set<String> fileNames) {
        if (fileNames.contains(file.getAbsolutePath())) {
            return;
        }
        fileNames.add(file.getAbsolutePath());
        if (file.isFile() && isMatch(file.getName(), extensions)) {
            result.add(file);
        } else if (file.isDirectory()) {
            File[] tempList = file.listFiles();
            for (File f : tempList) {
                listAllFiles(f, extensions, result, fileNames);
            }
        }
    }

    private static boolean isMatch(String fileName, String[] extensions) {
        if (extensions == null || extensions.length == 0) {
            return true;
        }
        String curExtension = FilenameUtils.getExtension(fileName).toLowerCase();
        for (String extension : extensions) {
            if (curExtension.equals(extension)) {
                return true;
            }
        }
        return false;
    }
}
